class_name JsonTest extends Control


const CHARS: String = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"


@onready var text_edit_json_string: TextEdit = $TextEditJsonString as TextEdit
@onready var item_list_godot_objects: ItemList = $ItemListGodotObjects as ItemList
@onready var text_edit_log: TextEdit = $TextEditLog as TextEdit
@onready var json: JSON = JSON.new()
@onready var rand: RandomNumberGenerator = RandomNumberGenerator.new()
@onready var chars_length: int = CHARS.length()

## 解析json字符串
func _on_button_json_to_godot_object_pressed() -> void:
	text_edit_log.text = ""
	var json_str: String = text_edit_json_string.text
	if json_str.is_empty():
		return
	var error: Error =  json.parse(json_str)
	if error == OK:
		var data: Variant = json.data
		text_edit_log.text = "解析成功。\n结果：\n{0}".format([ data ])
	else:
		var line: int = json.get_error_line()
		var message: String = json.get_error_message()
		text_edit_log.text = "解析失败。\n发生错误的行：{0}\n错误消息：{1}".format([ line, message ])
	

## 序列化godot对象
func _on_button_godot_object_to_json_pressed() -> void:
	text_edit_log.text = ""
	var obj: Variant = _get_godot_object()
	if obj == null:
		return
	var json_str: String = JSON.stringify(obj)
	text_edit_log.text = "序列化。\ngodot对象：\n{0}\n结果：\n{1}".format([ obj, json_str ])


func _get_godot_object() -> Variant:
	if not item_list_godot_objects.is_anything_selected():
		return null
	var selected_index: int = item_list_godot_objects.get_selected_items()[0]
	var selected_text: String = item_list_godot_objects.get_item_text(selected_index)
	match selected_text:
		"整数":
			return _get_int()
		"小数":
			return _get_float()
		"字符串":
			return _get_string()
		"逻辑":
			return _get_bool()
		"对象":
			return _get_simple_object()
		"数组":
			return _get_array()
		"字典":
			return _get_dictionary()
		"复杂对象":
			return _get_complex_object()
		_:
			return null


func _get_int() -> int:
	return rand.randi()
	
	
func _get_float() -> float:
	return rand.randf()
	

func _get_string() -> String:
	var str_length: int = rand.randi_range(5, 50)
	var s: String = ""
	var char_index: int
	for i in str_length:
		char_index = rand.randi_range(0, chars_length - 1)
		s += CHARS[char_index]
	return s
		

func _get_bool() -> bool:
	var i: int = rand.randi_range(0, 1)
	return i == 1
	

func _get_simple_object() -> Variant:
	return SimpleObject.new(_get_int(), _get_float(), _get_string(), _get_bool())


func _get_array() -> Array:
	return [ _get_int(), _get_float(), _get_string(), _get_bool() ]
	

func _get_dictionary() -> Dictionary:
	return {
		i = _get_int(),
		f = _get_float(),
		s = _get_string(),
		b = _get_bool(),
	}


func _get_complex_object() -> Variant:
	return ComplexObject.new(_get_int(), _get_float(), _get_string(), _get_bool())


## 简单对象
class SimpleObject extends RefCounted:
	var i: int
	var f: float
	var s: String
	var b: bool
	
	
	## 构造函数
	func _init(_i: int = 0, _f: float = 0.0, _s: String = "", _b: bool = false):
		i = _i
		f = _f
		s = _s
		b = _b
		
	
	## 转换成字符串
	func _to_string() -> String:
		return str(inst_to_dict(self))
	
	
	## 从字典解析
	static func from_dictionary(dict: Dictionary) -> SimpleObject:
		var obj: SimpleObject = SimpleObject.new()
		if not dict or not (dict is Dictionary) or dict.is_empty():
			return obj
		if dict.has("i"):
			obj.i = dict["i"]
		if dict.has("f"):
			obj.f = dict["f"]
		if dict.has("s"):
			obj.s = dict["s"]
		if dict.has("b"):
			obj.b = dict["b"]
		return obj
	
	
	## 从json字符串解析
	static func from_json_string(json_string: String) -> SimpleObject:
		var dict: Variant = JSON.parse_string(json_string)
		if not dict or not (dict is Dictionary) or dict.is_empty():
			dict = {}
		return from_dictionary(dict)
		

## 复杂对象
class ComplexObject extends RefCounted:
	var i: int
	var f: float
	var s: String
	var b: bool
	var arr: Array
	var dict: Dictionary
	
	
	## 构造函数
	func _init(_i: int = 0, _f: float = 0.0, _s: String = "", _b: bool = false):
		i = _i
		f = _f
		s = _s
		b = _b
		arr = [ SimpleObject.new(_i, _f, _s, _b), SimpleObject.new() ]
		dict = { 
			ii = i,
			ff = f,
			ss = s,
			bb = b,
		}
		
		
	## 转换成字符串
	func _to_string() -> String:
		return str(inst_to_dict(self))
